/**
 * 
 */
package jmine.tec.utils.cripto;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.security.Key;
import java.util.ArrayList;
import java.util.List;

/**
 * Esta classe provê métodos que auxiliam a encriptação e decriptação de um array de bytes.<br>
 * Deve ser definido um tamanho de segmentação de acordo com o tamanho da chave. Por padrão é setado um tamanho de 100 bytes que é usado
 * para uma chave de tamanho 1024.
 * 
 * @author gigante
 */
public class EncriptadorRSA {

    public static final int TAMANHO_CHAVE_1024 = 100;

    private final int segmentacao;

    /**
     * C'tor
     */
    public EncriptadorRSA() {
        this.segmentacao = TAMANHO_CHAVE_1024;
    }

    /**
     * C'tor
     * 
     * @param size o tamanho a ser segmentado
     */
    public EncriptadorRSA(final int size) {
        this.segmentacao = size;
    }

    /**
     * @return o tamanho da segmentação
     */
    public int getSegmentacao() {
        return this.segmentacao;
    }

    /**
     * Este método encripta uma mensagem em array de bytes e devolve uma MensagemEncriptada que guarda a os arrays encriptados que são
     * gerados pelo encriptador.<br>
     * 
     * @param mensagem o array de bytes a ser encriptado
     * @param chave a chave que será usada para encriptar o array passado
     * @return uma instância de MensagemEncriptada que guarda os arrays resultantes da encriptação
     */
    public MensagemEncriptada encriptaMensagem(final byte[] mensagem, final Key chave) {
        List<byte[]> list = new ArrayList<byte[]>();
        for (int i = 0; i < mensagem.length;) {
            int copySize = Math.min(mensagem.length - i, this.segmentacao);
            byte[] byteArray = new byte[copySize];
            System.arraycopy(mensagem, i, byteArray, 0, copySize);
            list.add(RSACriptoUtil.encripta(chave, byteArray));
            i += copySize;
        }
        return new MensagemEncriptada(list);
    }

    /**
     * Este método decripta uma instância de MensagemEncriptada.
     * 
     * @param mensagem a mensagem a ser decriptada
     * @param chave a chave pública que será usada para decriptar a mensagem passada
     * @return o array de bytes que é a mensagem decriptada
     */
    public byte[] decriptaMensagem(final MensagemEncriptada mensagem, final Key chave) {

        ByteArrayOutputStream out = new ByteArrayOutputStream();
        for (byte[] criptArray : mensagem.getMensagemEncriptada()) {
            byte[] decBytes = RSACriptoUtil.decripta(chave, criptArray);
            try {
                out.write(decBytes);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return out.toByteArray();
    }

}
